﻿using SkiaSharp;

namespace StudyCompanion.Commons.Image;

public class VerifyCode
{
    /// <summary>
    ///     字体大小
    /// </summary>
    private const int SetFontSize = 36;

    private static readonly Random ObjRandom = new();

    /// <summary>
    ///     构造函数
    /// </summary>
    public VerifyCode()
    {
    }

    /// <summary>
    ///     字体颜色
    /// </summary>
    private static SKColor SetFontColor { get; set; } = SKColors.Blue;

    /// <summary>
    ///     背景色
    /// </summary>
    private static SKColor SetBackgroundColor { get; } = SKColors.AliceBlue;

    /// <summary>
    ///     前景噪点数量
    /// </summary>
    private static int SetForeNoisePointCount { get; } = 2;

    /// <summary>
    ///     是否加入背景线
    /// </summary>
    private static bool SetIsBackgroundLine { get; } = true;

    /// <summary>
    ///     干扰线的颜色集合
    /// </summary>
    private static List<SKColor> Colors { get; set; }

    /// <summary>
    ///     获取验证码
    /// </summary>
    /// <param name="setVerifyCodeText">验证码文字</param>
    /// <param name="width">图片宽度</param>
    /// <param name="height">图片高度</param>
    /// <param name="lineNum">干扰线数量</param>
    /// <param name="lineWidth">干扰线宽度</param>
    /// <param name="setIsRandomColor">是否随机字体颜色</param>
    /// <returns></returns>
    public static byte[] GetVerifyCodeImage(string setVerifyCodeText, int width = 1000, int height = 40,
        int lineNum = 1, int lineWidth = 1, bool setIsRandomColor = true)
    {
        //创建bitmap位图
        using var image2d = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
        //创建画笔
        using var canvas = new SKCanvas(image2d);
        //填充文字颜色，默认蓝色
        if (setIsRandomColor) SetFontColor = GetRandomColor();
        //填充白色背景
        canvas.Clear(SetBackgroundColor);
        AddForeNoisePoint(image2d);
        AddBackgroundNoisePoint(image2d, canvas);
        //将文字写到画布上
        var drawStyle = new SKPaint();
        drawStyle.IsAntialias = true;
        drawStyle.TextSize = SetFontSize;
        var chars = setVerifyCodeText.ToCharArray();
        var font = SKTypeface.FromFile(Environment.CurrentDirectory + "/Source/VERDANA.TTF");
        drawStyle.Typeface = font;
        drawStyle.Color = SetFontColor;

        for (var i = 0; i < chars.Length; i++)
        {
            //转动的度数
            float angle = ObjRandom.Next(-30, 30);
            canvas.Translate(12, 12);
            float px = i * SetFontSize;
            float py = height / 2;
            canvas.RotateDegrees(angle, px, py);
            //写字 (i + 1) * 16, 28
            canvas.DrawText(chars[i].ToString(), px, py, drawStyle);
            canvas.RotateDegrees(-angle, px, py);
            canvas.Translate(-12, -12);
        }

        InitColors();
        //画随机干扰线
        using (var disturbStyle = new SKPaint())
        {
            var random = new Random();
            for (var i = 0; i < lineNum; i++)
            {
                disturbStyle.Color = Colors[random.Next(Colors.Count)];
                disturbStyle.StrokeWidth = lineWidth;
                canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width),
                    random.Next(0, height), disturbStyle);
            }
        }

        //返回图片byte
        using (var img = SKImage.FromBitmap(image2d))
        {
            using (var p = img.Encode(SKEncodedImageFormat.Png, 100))
            {
                return p.ToArray();
            }
        }
    }

    /// <summary>
    ///     获取随机颜色
    /// </summary>
    /// <returns></returns>
    private static SKColor GetRandomColor()
    {
        var randomNumFirst = new Random((int)DateTime.Now.Ticks);
        // 对于C#的随机数，没什么好说的
        Thread.Sleep(randomNumFirst.Next(50));
        var randomNumSecond = new Random((int)DateTime.Now.Ticks);
        // 为了在白色背景上显示，尽量生成深色
        var intRed = randomNumFirst.Next(256);
        var intGreen = randomNumSecond.Next(256);
        var intBlue = intRed + intGreen > 400 ? 0 : 400 - intRed - intGreen;
        intBlue = intBlue > 255 ? 255 : intBlue;
        return SKColor.FromHsv(intRed, intGreen, intBlue);
    }

    private static void AddForeNoisePoint(SKBitmap objBitmap)
    {
        for (var i = 0; i < objBitmap.Width * SetForeNoisePointCount; i++)
            objBitmap.SetPixel(ObjRandom.Next(objBitmap.Width), ObjRandom.Next(objBitmap.Height), SetFontColor);
    }

    /// <summary>
    ///     添加背景噪点
    /// </summary>
    /// <param name="objBitmap"></param>
    /// <param name="objGraphics"></param>
    private static void AddBackgroundNoisePoint(SKBitmap objBitmap, SKCanvas objGraphics)
    {
        using (var objPen = CreatePaint(SKColors.Azure, 0))
        {
            for (var i = 0; i < objBitmap.Width * 2; i++)
                objGraphics.DrawRect(ObjRandom.Next(objBitmap.Width), ObjRandom.Next(objBitmap.Height), 1, 1,
                    objPen);
        }

        // 是否添加背景线
        if (!SetIsBackgroundLine) return;
        {
            //画图片的背景噪音线
            for (var i = 0; i < 12; i++)
            {
                var x1 = ObjRandom.Next(objBitmap.Width);
                var x2 = ObjRandom.Next(objBitmap.Width);
                var y1 = ObjRandom.Next(objBitmap.Height);
                var y2 = ObjRandom.Next(objBitmap.Height);

                objGraphics.DrawLine(x1, y1, x2, y2, CreatePaint(SKColors.Silver, 0));
            }
        }
    }

    /// <summary>
    ///     创建画笔
    /// </summary>
    /// <param name="color"></param>
    /// <param name="fontSize"></param>
    /// <returns></returns>
    private static SKPaint CreatePaint(SKColor color, float fontSize)
    {
        var font = SKTypeface.FromFamilyName(null, SKFontStyleWeight.SemiBold,
            SKFontStyleWidth.ExtraCondensed, SKFontStyleSlant.Upright);
        var paint = new SKPaint();
        paint.IsAntialias = true;
        paint.Color = color;
        paint.Typeface = font;
        paint.TextSize = fontSize;
        return paint;
    }

    private static void InitColors()
    {
        Colors = new List<SKColor>
        {
            SKColors.AliceBlue,
            SKColors.PaleGreen,
            SKColors.PaleGoldenrod,
            SKColors.Orchid,
            SKColors.OrangeRed,
            SKColors.Orange,
            SKColors.OliveDrab,
            SKColors.Olive,
            SKColors.OldLace,
            SKColors.Navy,
            SKColors.NavajoWhite,
            SKColors.Moccasin,
            SKColors.MistyRose,
            SKColors.MintCream,
            SKColors.MidnightBlue,
            SKColors.MediumVioletRed,
            SKColors.MediumTurquoise,
            SKColors.MediumSpringGreen,
            SKColors.LightSlateGray,
            SKColors.LightSteelBlue,
            SKColors.LightYellow,
            SKColors.Lime,
            SKColors.LimeGreen,
            SKColors.Linen,
            SKColors.PaleTurquoise,
            SKColors.Magenta,
            SKColors.MediumAquamarine,
            SKColors.MediumBlue,
            SKColors.MediumOrchid,
            SKColors.MediumPurple,
            SKColors.MediumSeaGreen,
            SKColors.MediumSlateBlue,
            SKColors.Maroon,
            SKColors.PaleVioletRed,
            SKColors.PapayaWhip,
            SKColors.PeachPuff,
            SKColors.Snow,
            SKColors.SpringGreen,
            SKColors.SteelBlue,
            SKColors.Tan,
            SKColors.Teal,
            SKColors.Thistle,
            SKColors.SlateGray,
            SKColors.Tomato,
            SKColors.Violet,
            SKColors.Wheat,
            SKColors.White,
            SKColors.WhiteSmoke,
            SKColors.Yellow,
            SKColors.YellowGreen,
            SKColors.Turquoise,
            SKColors.LightSkyBlue,
            SKColors.SlateBlue,
            SKColors.Silver,
            SKColors.Peru,
            SKColors.Pink,
            SKColors.Plum,
            SKColors.PowderBlue,
            SKColors.Purple,
            SKColors.Red,
            SKColors.SkyBlue,
            SKColors.RosyBrown,
            SKColors.SaddleBrown,
            SKColors.Salmon,
            SKColors.SandyBrown,
            SKColors.SeaGreen,
            SKColors.SeaShell,
            SKColors.Sienna,
            SKColors.RoyalBlue,
            SKColors.LightSeaGreen,
            SKColors.LightSalmon,
            SKColors.LightPink,
            SKColors.Crimson,
            SKColors.Cyan,
            SKColors.DarkBlue,
            SKColors.DarkCyan,
            SKColors.DarkGoldenrod,
            SKColors.DarkGray,
            SKColors.Cornsilk,
            SKColors.DarkGreen,
            SKColors.DarkMagenta,
            SKColors.DarkOliveGreen,
            SKColors.DarkOrange,
            SKColors.DarkOrchid,
            SKColors.DarkRed,
            SKColors.DarkSalmon,
            SKColors.DarkKhaki,
            SKColors.DarkSeaGreen,
            SKColors.CornflowerBlue,
            SKColors.Chocolate,
            SKColors.AntiqueWhite,
            SKColors.Aqua,
            SKColors.Aquamarine,
            SKColors.Azure,
            SKColors.Beige,
            SKColors.Bisque,
            SKColors.Coral,
            SKColors.Black,
            SKColors.Blue,
            SKColors.BlueViolet,
            SKColors.Brown,
            SKColors.BurlyWood,
            SKColors.CadetBlue,
            SKColors.Chartreuse,
            SKColors.BlanchedAlmond,
            SKColors.Transparent,
            SKColors.DarkSlateBlue,
            SKColors.DarkTurquoise,
            SKColors.IndianRed,
            SKColors.Indigo,
            SKColors.Ivory,
            SKColors.Khaki,
            SKColors.Lavender,
            SKColors.LavenderBlush,
            SKColors.HotPink,
            SKColors.LawnGreen,
            SKColors.LightBlue,
            SKColors.LightCoral,
            SKColors.LightCyan,
            SKColors.LightGoldenrodYellow,
            SKColors.LightGray,
            SKColors.LightGreen,
            SKColors.LemonChiffon,
            SKColors.DarkSlateGray,
            SKColors.Honeydew,
            SKColors.Green,
            SKColors.DarkViolet,
            SKColors.DeepPink,
            SKColors.DeepSkyBlue,
            SKColors.DimGray,
            SKColors.DodgerBlue,
            SKColors.Firebrick,
            SKColors.GreenYellow,
            SKColors.FloralWhite,
            SKColors.Fuchsia,
            SKColors.Gainsboro,
            SKColors.GhostWhite,
            SKColors.Gold,
            SKColors.Goldenrod,
            SKColors.Gray,
            SKColors.ForestGreen
        };
    }
}